home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / svgakt50.zip / SRC / SVGAKIT / VBETEST.C < prev    next >
C/C++ Source or Header  |  1994-08-23  |  38KB  |  1,283 lines

  1. /****************************************************************************
  2. *
  3. *                  VBETest - VESA VBE stress test program
  4. *
  5. *                   Copyright (C) 1994 SciTech Software.
  6. *                           All rights reserved.
  7. *
  8. * Filename:     $RCSfile: vbetest.c $
  9. * Version:      $Revision: 1.1 $
  10. *
  11. * Language:     ANSI C
  12. * Environment:  IBM PC (MS DOS)
  13. *
  14. * Description:    VBETest test program. This program is designed to stress
  15. *                test a VESA VBE implementation, and check it for full
  16. *                conformance with the VBE standard that it claims to conform
  17. *                to (supports only standards >= 1.2 standard).
  18. *
  19. *                This program uses the SuperVGA test kit to perform all
  20. *                graphics output when testing the appropriate video modes
  21. *                for conformance (and thus only works on 386 and above
  22. *                machines).
  23. *
  24. *               MUST be compiled in the large memory model.
  25. *
  26. *                This program is freely distributable in the executable
  27. *                form. The source code is under the same restrictions as
  28. *                the SuperVGA kit it belong in.
  29. *
  30. * $Id: vbetest.c 1.1 1994/08/22 12:27:00 kjb release $
  31. *
  32. ****************************************************************************/
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <stdarg.h>
  37. #include <dos.h>
  38. #include <string.h>
  39. #include <conio.h>
  40. #include <ctype.h>
  41. #include "svga.h"
  42. #include "getopt.h"
  43.  
  44. /*----------------------------- Implementation ----------------------------*/
  45.  
  46. /* Special UniVBE Information Block */
  47.  
  48. typedef struct {
  49.     char    SuperVGAName[50];        /* Name of installed SuperVGA        */
  50.     char    DACName[50];            /* Name of installed DAC            */
  51.     short    SuperVGA;                /* UniVBE SuperVGA id number        */
  52.     short    ChipID;                    /* UniVBE Chipset id number            */
  53.     short    Memory;                    /* Amount of memory installed        */
  54.     short    DacID;                    /* UniVBE DAC id number                */
  55.     } UniVBEInfo;
  56.  
  57. /* SuperVGA information block */
  58.  
  59. typedef struct {
  60.     char    VESASignature[4];       /* 'VESA' 4 byte signature          */
  61.     short   VESAVersion;            /* VBE version number               */
  62.     long    OEMStringPtr;           /* Far pointer to OEM string        */
  63.     long    Capabilities;           /* Capabilities of video card       */
  64.     long    VideoModePtr;           /* Far pointer to supported modes   */
  65.     short   TotalMemory;            /* Number of 64kb memory blocks     */
  66.     char    reserved[232];          /* Pad to 256 byte block size       */
  67.     UniVBEInfo    far *univbeInfo;    /* Special UniVBE information block    */
  68.     } VgaInfoBlock;
  69.  
  70. /* SuperVGA mode information block */
  71.  
  72. typedef struct {
  73.     short   ModeAttributes;         /* Mode attributes                  */
  74.     char    WinAAttributes;         /* Window A attributes              */
  75.     char    WinBAttributes;         /* Window B attributes              */
  76.     short   WinGranularity;         /* Window granularity in k          */
  77.     short   WinSize;                /* Window size in k                 */
  78.     short   WinASegment;            /* Window A segment                 */
  79.     short   WinBSegment;            /* Window B segment                 */
  80.     long    WinFuncPtr;                /* Far pointer to window function   */
  81.     short   BytesPerScanLine;       /* Bytes per scanline               */
  82.     short   XResolution;            /* Horizontal resolution            */
  83.     short   YResolution;            /* Vertical resolution              */
  84.     char    XCharSize;              /* Character cell width             */
  85.     char    YCharSize;              /* Character cell height            */
  86.     char    NumberOfPlanes;         /* Number of memory planes          */
  87.     char    BitsPerPixel;           /* Bits per pixel                   */
  88.     char    NumberOfBanks;          /* Number of CGA style banks        */
  89.     char    MemoryModel;            /* Memory model type                */
  90.     char    BankSize;               /* Size of CGA style banks          */
  91.     char    NumberOfImagePages;     /* Number of images pages           */
  92.     char    res1;                   /* Reserved                         */
  93.     char    RedMaskSize;            /* Size of direct color red mask    */
  94.     char    RedFieldPosition;       /* Bit posn of lsb of red mask      */
  95.     char    GreenMaskSize;          /* Size of direct color green mask  */
  96.     char    GreenFieldPosition;     /* Bit posn of lsb of green mask    */
  97.     char    BlueMaskSize;           /* Size of direct color blue mask   */
  98.     char    BlueFieldPosition;      /* Bit posn of lsb of blue mask     */
  99.     char    RsvdMaskSize;           /* Size of direct color res mask    */
  100.     char    RsvdFieldPosition;      /* Bit posn of lsb of res mask      */
  101.     char    DirectColorModeInfo;    /* Direct color mode attributes     */
  102.     char    res2[216];              /* Pad to 256 byte block size       */
  103.     } ModeInfoBlock;
  104.  
  105. typedef struct {
  106.     int        ax,bx,cx,dx,si,di,es,ds;
  107.     } regs;
  108.  
  109. FILE    *logfile = NULL;
  110. int        CP_x,CP_y,VBEVersion,maxbanks,VBEFunc = 0,numErrors = 0,bits = 0;
  111. int        VBEMode = 0;
  112. bool    failed = false;
  113. bool    verbose = false;
  114. bool    doPageTest = false;
  115. short    modelist[100];
  116.  
  117. #include "version.c"
  118.  
  119. /* Table of memory model names */
  120.  
  121. char *memModelNames[] = {
  122.     "Text Mode",
  123.     "CGA Graphics",
  124.     "Hercules Graphics",
  125.     "4-plane planar",
  126.     "Packed Pixel",
  127.     "Non-chain 4, 256 color",
  128.     "Direct Color RGB",
  129.     "Direct Color YUV",
  130.     };
  131.  
  132. int queryCpu(void);
  133.  
  134. void out(const char *fmt, ... )
  135. {
  136.     va_list argptr;
  137.  
  138.     va_start(argptr, fmt);
  139.     vfprintf(stdout, fmt, argptr);
  140.     if (logfile)
  141.         vfprintf(logfile, fmt, argptr);
  142.     va_end(argptr);
  143. }
  144.  
  145. void log(const char *fmt, ... )
  146. {
  147.     va_list argptr;
  148.  
  149.     va_start(argptr, fmt);
  150.     if (logfile) {
  151.         vfprintf(logfile, fmt, argptr);
  152.         fflush(logfile);
  153.         }
  154.     va_end(argptr);
  155. }
  156.  
  157. /* Routine to convert the input value to its binary representation */
  158.  
  159. char *binary(unsigned value)
  160. {
  161.     static char    buf[11] = "00000000b";
  162.     unsigned    mask = 0x80;
  163.     int         i;
  164.  
  165.     for (i = 0; i < 8; i++) {
  166.         buf[i] = value & mask ? '1' : '0';
  167.         mask >>= 1;
  168.         }
  169.  
  170.     return buf;
  171. }
  172.  
  173. bool checkEscape(void)
  174. /****************************************************************************
  175. *
  176. * Function:        checkEscape
  177. * Returns:        True if key was hit to advance to next test.
  178. *
  179. * Description:    Checks if ESC has been hit, and exits if so.
  180. *
  181. ****************************************************************************/
  182. {
  183.     if (kbhit()) {
  184.         int ch = getch();
  185.         if (ch == 0) getch();
  186.         if (ch == 0x1B) {
  187.             restoreMode();
  188.             exit(1);
  189.             }
  190.         return true;
  191.         }
  192.     return false;
  193. }
  194.  
  195. void startCheck(int _VBEFunc)
  196. /****************************************************************************
  197. *
  198. * Function:        startCheck
  199. * Parameters:    _VBEFunc    - VBE Function number we are currently checking
  200. *
  201. * Description:    Begins the logging of errors for this function.
  202. *
  203. ****************************************************************************/
  204. {
  205.     log("Checking function %02Xh ... ", VBEFunc = _VBEFunc);
  206.     numErrors = 0;
  207. }
  208.  
  209. void endCheck(void)
  210. /****************************************************************************
  211. *
  212. * Function:        endCheck
  213. *
  214. * Description:    Ends the checking of a particular VBE function.
  215. *
  216. ****************************************************************************/
  217. {
  218.     if (numErrors == 0)
  219.         log("Passed.\n");
  220.     else
  221.         log("\n%d errors logged for function %02Xh.\n", numErrors, VBEFunc);
  222. }
  223.  
  224. void startModeCheck(int mode)
  225. /****************************************************************************
  226. *
  227. * Function:        startModeCheck
  228. * Parameters:    mode    - VBE mode number being checked
  229. *
  230. * Description:    Begins the logging of errors for this mode.
  231. *
  232. ****************************************************************************/
  233. {
  234.     log("Checking mode %02Xh ... ", VBEMode = mode);
  235.     if (verbose) log("\n");
  236.     numErrors = 0;
  237. }
  238.  
  239. void endModeCheck(void)
  240. /****************************************************************************
  241. *
  242. * Function:        endModeCheck
  243. *
  244. * Description:    Ends the checking of a particular VBE mode.
  245. *
  246. ****************************************************************************/
  247. {
  248.     if (numErrors == 0)
  249.         log("Passed.\n");
  250.     else
  251.         log("\n%d errors logged for mode %02Xh.\n", numErrors, VBEMode);
  252. }
  253.  
  254. void fail(const char *msg, ... )
  255. /****************************************************************************
  256. *
  257. * Function:        fail
  258. * Parameters:    msg    - Message describing error
  259. *
  260. * Description:    Logs a failure message to the log file outlining the problem
  261. *                that was encountered.
  262. *
  263. ****************************************************************************/
  264. {
  265.     va_list argptr;
  266.  
  267.     if (numErrors == 0)
  268.         log("\n\n");
  269.     numErrors++;
  270.     failed = true;
  271.  
  272.     va_start(argptr, msg);
  273.     fprintf(logfile,"    ");
  274.     vfprintf(logfile, msg, argptr);
  275.     va_end(argptr);
  276. }
  277.  
  278. bool callVBE(regs *r)
  279. /****************************************************************************
  280. *
  281. * Function:        callVBE
  282. * Parameters:    r    - Structure holding register values to load
  283. * Returns:        True if successful, false if function failed
  284. *
  285. * Description:    Loads the appropriate registers with the values from
  286. *                the register structure and executes and int 10h to call
  287. *                the VBE. It checks to ensure that register values are
  288. *                preserved across all calls correctly and ensures that the
  289. *               function executed successfully.
  290. *
  291. ****************************************************************************/
  292. {
  293.     union REGS        rg;
  294.     struct SREGS    sr;
  295.     int                mask;
  296.  
  297.     rg.x.ax = r->ax;    rg.x.bx = r->bx;
  298.     rg.x.cx = r->cx;    rg.x.dx = r->dx;
  299.     rg.x.si = r->si;    rg.x.di = r->di;
  300.     sr.es = r->es;        sr.ds = r->ds;
  301.     int86x(0x10,&rg,&rg,&sr);
  302.  
  303.     if ((r->ax >> 8) != 0x4F) return TRUE;
  304.  
  305.     /* Check to ensure all register are preserved across call. We define
  306.      * the mask to be a one for a register that must be preserved, and
  307.      * a zero for a register that can change. AX is always the result
  308.      * code, so this leave 7 bits to represent each register.
  309.      */
  310.  
  311.     switch (r->ax & 0xFF) {
  312.         case 0x00:    mask = 0x7F;    break;
  313.         case 0x01:    mask = 0x7F;    break;
  314.         case 0x02:    mask = 0x7F;    break;
  315.         case 0x03:    mask = 0x7E;    break;
  316.         case 0x04:    if ((r->dx & 0xFF) == 0)
  317.                         mask = 0x7E;        /* State size call        */
  318.                     else mask = 0x7F;        /* Other calls            */
  319.                     break;
  320.         case 0x05:    if ((r->bx >> 8) == 0)
  321.                         mask = 0x7F;        /* Set window call        */
  322.                     else mask = 0x7B;        /* Get window call        */
  323.                     break;
  324.         case 0x06:    mask = 0x78;    break;
  325.         case 0x07:    if (r->bx == 0)
  326.                         mask = 0x7F;        /* Set display start    */
  327.                     else mask = 0x78;        /* Get display start    */
  328.                     break;
  329.         case 0x08:    mask = 0x7E;    break;
  330.         default:    mask = 0;
  331.         }
  332.  
  333.     if ((mask & 0x01) && (r->bx != rg.x.bx))
  334.         fail("Function %02Xh failed to preserve BX\n", r->ax & 0xFF);
  335.     if ((mask & 0x02) && (r->cx != rg.x.cx))
  336.         fail("Function %02Xh failed to preserve CX\n", r->ax & 0xFF);
  337.     if ((mask & 0x04) && (r->dx != rg.x.dx))
  338.         fail("Function %02Xh failed to preserve DX\n", r->ax & 0xFF);
  339.     if (r->si != rg.x.si)
  340.         fail("Function %02Xh failed to preserve SI\n", r->ax & 0xFF);
  341.     if (r->di != rg.x.di)
  342.         fail("Function %02Xh failed to preserve DI\n", r->ax & 0xFF);
  343.     if (r->ds != sr.ds)
  344.         fail("Function %02Xh failed to preserve DS\n", r->ax & 0xFF);
  345.     if (r->es != sr.es)
  346.         fail("Function %02Xh failed to preserve ES\n", r->ax & 0xFF);
  347.  
  348.     r->ax = rg.x.ax;    r->bx = rg.x.bx;
  349.     r->cx = rg.x.cx;    r->dx = rg.x.dx;
  350.     r->si = rg.x.si;    r->di = rg.x.di;
  351.     r->es = sr.es;        r->ds = sr.ds;
  352.  
  353.     return (r->ax == 0x004F);
  354. }
  355.  
  356. void checkFunction00h(void)
  357. /****************************************************************************
  358. *
  359. * Function:        checkFunction00h
  360. *
  361. * Description:    Calls function 00h to determine if a VESA VBE is present,
  362. *                and check it for conformance.
  363. *
  364. ****************************************************************************/
  365. {
  366.     VgaInfoBlock    vgaInfo;
  367.     regs            r;
  368.     short            i,*modes;
  369.  
  370.     r.es = SEG(&vgaInfo);
  371.     r.di = OFF(&vgaInfo);
  372.     r.ax = 0x4F00;
  373.     if (callVBE(&r)) {
  374.         if (vgaInfo.VESAVersion < 0x102) {
  375.             out("Detected a VBE %d.%d interface. This program only checks interfaces that\n",
  376.                 vgaInfo.VESAVersion >> 0x8,vgaInfo.VESAVersion & 0xF);
  377.             out("conform to the VBE 1.2 or later specifications.\n");
  378.             exit(1);
  379.             }
  380.  
  381.         printf("VBE %d.%d Interface detected - checking for conformance\n\n",
  382.             vgaInfo.VESAVersion >> 0x8,vgaInfo.VESAVersion & 0xF);
  383.  
  384.         log("VBE Version:  %d.%d\n",vgaInfo.VESAVersion >> 0x8,
  385.             vgaInfo.VESAVersion & 0xF);
  386.         log("OEMString:    %s\n",vgaInfo.OEMStringPtr);
  387.         log("Capabilities: %s (%04Xh)\n",binary(vgaInfo.Capabilities),
  388.             vgaInfo.Capabilities);
  389.         log("Total Memory: %d Kb\n",memory = vgaInfo.TotalMemory * 64);
  390.         if (verbose && vgaInfo.univbeInfo) {
  391.             log("\nUniVBE is installed. Current configuration:\n");
  392.             log("    %s\n", vgaInfo.univbeInfo->SuperVGAName);
  393.             log("    %s\n", vgaInfo.univbeInfo->DACName);
  394.             }
  395.         log("\nAvailable Modes:\n\n");
  396.  
  397.         modes = (short*)vgaInfo.VideoModePtr;
  398.         i = 0;
  399.         while (*modes != -1) {
  400.             modelist[i] = *modes;
  401.             log("%04Xh ",*modes++);
  402.             if ((++i % 10) == 0)
  403.                 log("\n");
  404.             }
  405.         modelist[i] = -1;
  406.         log("\n\n");
  407.         startCheck(0x00);
  408.         if (vgaInfo.TotalMemory == 0)
  409.             fail("TotalMemory field is zero!");
  410.         endCheck();
  411.  
  412.         VBEVersion = vgaInfo.VESAVersion;
  413.         maxbanks = vgaInfo.TotalMemory;
  414.         }
  415.     else {
  416.         out("VESA VBE interface not detected.\n");
  417.         exit(1);
  418.         }
  419. }
  420.  
  421. void checkFunction01h(void)
  422. /****************************************************************************
  423. *
  424. * Function:        checkFunction01h
  425. *
  426. * Description:    Calls function 01h to obtain information about all
  427. *                available video modes, checking the values returned in the
  428. *                structure.
  429. *
  430. ****************************************************************************/
  431. {
  432.     ModeInfoBlock    modeInfo;
  433.     regs            r;
  434.     short            *modes;
  435.  
  436.     startCheck(0x01);
  437.     for (modes = modelist; *modes != -1; modes++) {
  438.         r.es = SEG(&modeInfo);
  439.         r.di = OFF(&modeInfo);
  440.         r.ax = 0x4F01;
  441.         r.cx = *modes;
  442.         if (callVBE(&r)) {
  443.             /* Ignore unsupported and text modes */
  444.             if ((modeInfo.ModeAttributes & 0x1) == 0)
  445.                 continue;
  446.             if ((modeInfo.ModeAttributes & 0x10) == 0)
  447.                 continue;
  448.             if (modeInfo.WinGranularity > 64 || modeInfo.WinGranularity == 0)
  449.                 fail("Bad window granularity factor: %d\n",modeInfo.WinGranularity);
  450.             if (modeInfo.WinSize > 64 || modeInfo.WinSize == 0)
  451.                 fail("Bad window size: %d\n",modeInfo.WinSize);
  452.             if ((modeInfo.WinAAttributes & 0x1) && modeInfo.WinASegment == 0)
  453.                 fail("Bad window A segment value: %04Xh\n", modeInfo.WinASegment);
  454.             if ((modeInfo.WinBAttributes & 0x1) && modeInfo.WinBSegment == 0)
  455.                 fail("Bad window B segment value: %04Xh\n", modeInfo.WinBSegment);
  456.             if (modeInfo.WinFuncPtr == NULL)
  457.                 fail("NULL window function pointer\n");
  458.             }
  459.         else
  460.             fail("Video mode %03Xh not available yet listed in mode list\n", *modes);
  461.         }
  462.     endCheck();
  463. }
  464.  
  465. void checkFunction02h(void)
  466. /****************************************************************************
  467. *
  468. * Function:        checkFunction02h
  469. *
  470. * Description:    Calls function 02h to set each of the available video modes,
  471. *                draw a pattern and display status information about each
  472. *                video mode.
  473. *
  474. ****************************************************************************/
  475. {
  476.     ModeInfoBlock    modeInfo;
  477.     regs            r;
  478.     short            *modes;
  479.  
  480.     startCheck(0x02);
  481.     for (modes = modelist; *modes != -1; modes++) {
  482.         r.es = SEG(&modeInfo);
  483.         r.di = OFF(&modeInfo);
  484.         r.ax = 0x4F01;
  485.         r.cx = *modes;
  486.         if (callVBE(&r)) {
  487.             if ((modeInfo.ModeAttributes & 0x1) == 0)
  488.                 continue;
  489.             r.ax = 0x4F02;
  490.             r.bx = *modes;
  491.             if (callVBE(&r)) {
  492.                 r.ax = 0x4F03;
  493.                 callVBE(&r);
  494.                 if (r.bx != *modes)
  495.                     fail("Function 03h did not return same video mode number (%04Xh instead of %04Xh)\n", r.bx, *modes);
  496.                 }
  497.             }
  498.         }
  499.     r.ax = 0x3;
  500.     callVBE(&r);
  501.     endCheck();
  502. }
  503.  
  504. void checkFunction04h(void)
  505. /****************************************************************************
  506. *
  507. * Function:        checkFunction04h
  508. *
  509. * Description:    Calls function 04h to save and restore the SuperVGA
  510. *                video state.
  511. *
  512. ****************************************************************************/
  513. {
  514.     regs            r;
  515.     int                size;
  516.     void            *savebuf;
  517.  
  518.     startCheck(0x04);
  519.     r.ax = 0x4F04;
  520.     r.dx = 0x0000;
  521.     r.cx = 0x000F;
  522.     if (!callVBE(&r))
  523.         fail("Function 04h subfunction 00h failed.\n");
  524.     size = r.bx * 64;
  525.     if (size < 960)
  526.         fail("Invalid buffer size.\n");
  527.     if ((savebuf = malloc(size)) == NULL)
  528.         exit(1);
  529.  
  530.     r.ax = 0x4F04;
  531.     r.dx = 0x0001;
  532.     r.cx = 0x000F;
  533.     r.es = SEG(savebuf);
  534.     r.bx = OFF(savebuf);
  535.     if (!callVBE(&r))
  536.         fail("Function 04h subfunction 01h failed.\n");
  537.  
  538.     r.ax = 0x4F04;
  539.     r.dx = 0x0002;
  540.     r.cx = 0x000F;
  541.     r.es = SEG(savebuf);
  542.     r.bx = OFF(savebuf);
  543.     if (!callVBE(&r))
  544.         fail("Function 04h subfunction 02h failed.\n");
  545.  
  546.     r.ax = 0x3;
  547.     callVBE(&r);
  548.  
  549.     free(savebuf);
  550.     endCheck();
  551. }
  552.  
  553. void checkFunction05h(void)
  554. /****************************************************************************
  555. *
  556. * Function:        checkFunction05h
  557. *
  558. * Description:    Calls function 05h to change the video memory banks from
  559. *                the first bank all the way down to the last bank, and
  560. *                to read the bank values back again.
  561. *
  562. ****************************************************************************/
  563. {
  564.     ModeInfoBlock    modeInfo;
  565.     regs            r;
  566.     int                bank;
  567.     bool            twobanks;
  568.  
  569.     startCheck(0x05);
  570.  
  571.     r.es = SEG(&modeInfo);
  572.     r.di = OFF(&modeInfo);
  573.     r.ax = 0x4F01;
  574.     r.cx = 0x102;
  575.     callVBE(&r);
  576.     twobanks = modeInfo.WinBAttributes & 0x1;
  577.  
  578.     r.ax = 0x4F02;
  579.     r.bx = 0x102;
  580.     if (!callVBE(&r))
  581.         fail("Could not set 800x600x16 color mode\n");
  582.  
  583.     for (bank = 0; bank < maxbanks; bank++) {
  584.         r.ax = 0x4F05;
  585.         r.bx = 0x0000;
  586.         r.dx = bank;
  587.         if (!callVBE(&r))
  588.             fail("Bank switch routine failed.\n");
  589.         r.ax = 0x4F05;
  590.         r.bx = 0x0100;
  591.         if (!callVBE(&r))
  592.             fail("Bank switch routine failed.\n");
  593.         if (r.dx != bank)
  594.             fail("Differing bank 1 value returned (%04Xh instead of %04Xh)\n", r.dx, bank);
  595.  
  596.         if (twobanks) {
  597.             r.ax = 0x4F05;
  598.             r.bx = 0x0001;
  599.             r.dx = bank;
  600.             if (!callVBE(&r))
  601.                 fail("Bank switch routine failed.\n");
  602.             r.ax = 0x4F05;
  603.             r.bx = 0x0101;
  604.             if (!callVBE(&r))
  605.                 fail("Bank switch routine failed.\n");
  606.             if (r.dx != bank)
  607.                 fail("Differing bank 2 value returned (%04Xh instead of %04Xh)\n", r.dx, bank);
  608.             }
  609.         }
  610.  
  611.     r.ax = 0x3;
  612.     callVBE(&r);
  613.     endCheck();
  614. }
  615.  
  616. void clearAllPages(void)
  617. /****************************************************************************
  618. *
  619. * Function:        clearAllPages
  620. *
  621. * Description:    Clears the entire video memory to black.
  622. *
  623. ****************************************************************************/
  624. {
  625.     int        i;
  626.     char    far *vmem = MK_FP(0xA000,0x0000);
  627.  
  628.     for (i = 0; i < maxbanks; i++) {
  629.         setBank(i);
  630.         memset(vmem,0,0x7FFF);
  631.         memset(vmem+0x7FFF,0,0x7FFF);
  632.         }
  633. }
  634.  
  635. void setDisplayStart(int x,int y)
  636. /****************************************************************************
  637. *
  638. * Function:     setDisplayStart
  639. * Parameters:   x,y - Position of the first pixel to display
  640. *
  641. * Description:  Sets the new starting display position to implement
  642. *               hardware scrolling.
  643. *
  644. ****************************************************************************/
  645. {
  646.     regs    r;
  647.  
  648.     if (extendedflipping) {
  649.         r.ax = 0x4F07;
  650.         r.bx = 0x0000;
  651.         r.cx = x;
  652.         r.dx = y;
  653.         callVBE(&r);
  654.         r.ax = 0x4F07;
  655.         r.bx = 0x0001;
  656.         callVBE(&r);
  657.         if (abs(r.cx-x) > 8 || r.dx != y) {
  658.             fail("Invalid values returned by Function 07h subfunction 01h (cx = %04Xh, dx = %04Xh)\n", r.cx, r.dx);
  659.             fail("Should have been cx = %04Xh (can be rounded down), dx = %04Xh\n", x, y);
  660.             }
  661.         }
  662. }
  663.  
  664. void setScanlineLength(int width,int *bytesperline,int *maxx,int *maxy)
  665. /****************************************************************************
  666. *
  667. * Function:        setScanlineLength
  668. * Parameters:    width            - New scanline width to set in pixels
  669. *                bytesperline    - New bytes per line value
  670. *                maxx            - New maximum X coordinate
  671. *                maxy            - New maximum Y coordinate
  672. *
  673. * Description:    Attempts to set the logical scanline length using the
  674. *                VBE function 06h to set up a logical display buffer.
  675. *
  676. ****************************************************************************/
  677. {
  678.     regs    r,r2;
  679.  
  680.     r.ax = 0x4F06;
  681.     r.bx = 0x0000;
  682.     r.cx = width;
  683.     if (!callVBE(&r))
  684.         fail("Function 06h subfunction 00h failed.\n");
  685.  
  686.     r2.ax = 0x4F06;
  687.     r2.bx = 0x0001;
  688.     if (!callVBE(&r2))
  689.         fail("Function 06h subfunction 01h failed.\n");
  690.  
  691.     if (r.bx != r2.bx)
  692.         fail("Differing bytes per scanline values (%04Xh instead of %04Xh).\n",
  693.             r2.bx, r.bx);
  694.     if (r.cx != r2.cx)
  695.         fail("Differing pixels per scanline values (%04Xh instead of %04Xh).\n",
  696.             r2.cx, r.cx);
  697.     if (r.dx != r2.dx)
  698.         fail("Differing maximum scanline values (%04Xh instead of %04Xh).\n",
  699.             r2.dx, r.dx);
  700.  
  701.     *bytesperline = r.bx;
  702.     *maxx = r.cx-1;
  703.     *maxy = r.dx-1;
  704. }
  705.  
  706. void moire(void)
  707. /****************************************************************************
  708. *
  709. * Function:     moire
  710. *
  711. * Description:  Draws a simple Moire pattern on the display screen using
  712. *               lines.
  713. *
  714. ****************************************************************************/
  715. {
  716.     int     i,value;
  717.  
  718.     clearAllPages();
  719.     if (maxcolor <= 255) {
  720.         for (i = 0; i < maxx; i += 10) {
  721.             line(maxx/2,maxy/2,i,0,i % maxcolor);
  722.             line(maxx/2,maxy/2,i,maxy,(i+1) % maxcolor);
  723.             }
  724.         for (i = 0; i < maxy; i += 10) {
  725.             line(maxx/2,maxy/2,0,i,(i+2) % maxcolor);
  726.             line(maxx/2,maxy/2,maxx,i,(i+3) % maxcolor);
  727.             }
  728.         }
  729.     else {
  730.         for (i = 0; i < maxx; i++) {
  731.             line(maxx/2,maxy/2,i,0,rgbColor(((i*255L)/maxx),0,0));
  732.             line(maxx/2,maxy/2,i,maxy,rgbColor(0,((i*255L)/maxx),0));
  733.             }
  734.         for (i = 0; i < maxy; i++) {
  735.             value = (i*255L)/maxy;
  736.             line(maxx/2,maxy/2,0,i,rgbColor(value,0,255 - value));
  737.             line(maxx/2,maxy/2,maxx,i,rgbColor(0,255 - value,value));
  738.             }
  739.         }
  740.     line(0,0,maxx,0,defcolor);
  741.     line(0,0,0,maxy,defcolor);
  742.     line(maxx,0,maxx,maxy,defcolor);
  743.     line(0,maxy,maxx,maxy,defcolor);
  744. }
  745.  
  746. void gprintf(const char *fmt, ... )
  747. /****************************************************************************
  748. *
  749. * Function:        gprintf
  750. * Parameters:    fmt    - Format string to display
  751. *
  752. * Description:    Displays a string in the current display mode.
  753. *
  754. ****************************************************************************/
  755. {
  756.     va_list argptr;
  757.     char    buf[255];
  758.  
  759.     va_start(argptr, fmt);
  760.     vsprintf(buf,fmt,argptr);
  761.     writeText(CP_x,CP_y,buf,defcolor);
  762.     if (verbose) log("    %s\n", buf);
  763.     CP_y += 16;
  764.     va_end(argptr);
  765. }
  766.  
  767. void dumpModeInfo(int mode,int displayAll)
  768. /****************************************************************************
  769. *
  770. * Function:     dumpModeInfo
  771. * Parameters:   mode        - Mode number to dump info for
  772. *                displayAll    - Should we display all mode info?
  773. *
  774. * Description:  Dumps the information about the specific mode to the
  775. *               display.
  776. *
  777. ****************************************************************************/
  778. {
  779.     ModeInfoBlock   modeInfo;
  780.     union REGS      regs;
  781.     struct SREGS    sregs;
  782.  
  783.     sregs.es = FP_SEG(&modeInfo);
  784.     regs.x.di = FP_OFF(&modeInfo);
  785.     regs.x.ax = 0x4F01;
  786.     regs.x.cx = mode;
  787.     int86x(0x10,®s,®s,&sregs);
  788.     if ((modeInfo.ModeAttributes & 0x1) == 0)
  789.         return;
  790.     CP_x = CP_y = 5;
  791.     if (verbose)
  792.         log("\nMode information:\n");
  793.     gprintf("Mode number:     %04Xh",mode);
  794.     if (displayAll) {
  795.         gprintf("ModeAttributes:  %s (%04Xh)",binary(modeInfo.ModeAttributes),
  796.             modeInfo.ModeAttributes);
  797.         gprintf("WinAAttributes:  %s (%04Xh)",binary(modeInfo.WinAAttributes),
  798.             modeInfo.WinAAttributes);
  799.         gprintf("WinBAttributes:  %s (%04Xh)",binary(modeInfo.WinBAttributes),
  800.             modeInfo.WinBAttributes);
  801.         gprintf("WinGranulatiry:  %d",modeInfo.WinGranularity);
  802.         gprintf("WinSize:         %d",modeInfo.WinSize);
  803.         gprintf("WinASegment:     %04Xh",modeInfo.WinASegment);
  804.         gprintf("WinBSegment:     %04Xh",modeInfo.WinBSegment);
  805.         gprintf("WinFuncPtr:      %04X:%04X",FP_SEG(modeInfo.WinFuncPtr),
  806.             FP_OFF(modeInfo.WinFuncPtr));
  807.         }
  808.     if (modeInfo.ModeAttributes & 0x10) {
  809.         gprintf("Resolution:      %d x %d x %d bits per pixel (%02Xh BytesPerLine)",
  810.             modeInfo.XResolution,modeInfo.YResolution,modeInfo.BitsPerPixel,
  811.             modeInfo.BytesPerScanLine);
  812.         if (displayAll) {
  813.             gprintf("MemoryModel:     %s",memModelNames[modeInfo.MemoryModel]);
  814.             gprintf("");
  815.             gprintf("CharSize:        %d x %d",
  816.                 modeInfo.XCharSize,modeInfo.YCharSize);
  817.             if (modeInfo.MemoryModel >= 6) {
  818.                 gprintf("Red Component:   %d bits, position %d",
  819.                     modeInfo.RedMaskSize,modeInfo.RedFieldPosition);
  820.                 gprintf("Green Component: %d bits, position %d",
  821.                     modeInfo.GreenMaskSize,modeInfo.GreenFieldPosition);
  822.                 gprintf("Blue Component:  %d bits, position %d",
  823.                     modeInfo.BlueMaskSize,modeInfo.BlueFieldPosition);
  824.                 gprintf("Rsvd Component:  %d bits, position %d",
  825.                     modeInfo.RsvdMaskSize,modeInfo.RsvdFieldPosition);
  826.                 gprintf("DirectColorInfo: %s (%d)",
  827.                     binary(modeInfo.DirectColorModeInfo),
  828.                     modeInfo.DirectColorModeInfo);
  829.                 }
  830.             }
  831.         }
  832.     else {
  833.         gprintf("Resolution:      %d x %d Text Mode (%d x %d charsize)",
  834.             modeInfo.XResolution,modeInfo.YResolution,
  835.             modeInfo.XCharSize,modeInfo.YCharSize);
  836.         }
  837.     gprintf("NumberOfPages:   %d",modeInfo.NumberOfImagePages+1);
  838.     if (verbose)
  839.         log("\n");
  840. }
  841.  
  842. void pageTest(int mode)
  843. /****************************************************************************
  844. *
  845. * Function:        pageTest
  846. *
  847. * Description:    Interactive debugging of CRTC paging. We render an image to
  848. *                each of the available display pages, and then flip through
  849. *                the pages one by one, or to a specified display page
  850. *                depending on what the user specifies. We finish when the
  851. *                users hits the enter key (or quit on ESC).
  852. *
  853. ****************************************************************************/
  854. {
  855.     int     i,ch,vpage,done = 0;
  856.     char    buf[80];
  857.  
  858.     /* Cycle through each of the display pages, printing the page number
  859.      * so that we can identify the page correctly.
  860.      */
  861.  
  862.     for (i = 0; i <= maxpage; i++) {
  863.         setActivePage(i);
  864.         moire();
  865.         dumpModeInfo(mode,false);
  866.         gprintf("");
  867.         gprintf("Page %d of %d", i+1, maxpage+1);
  868.         gprintf("u   - Move up one page");
  869.         gprintf("d   - Move down one page");
  870.         gprintf("U   - Cycle up continuously (any key to stop)");
  871.         gprintf("D   - Cycle down continuously (any key to stop)");
  872.         gprintf("1-9 - Display specified page");
  873.         line(0,0,maxx,0,defcolor);
  874.         line(0,0,0,maxy,defcolor);
  875.         line(maxx,0,maxx,maxy,defcolor);
  876.         line(0,maxy,maxx,maxy,defcolor);
  877.         }
  878.     vpage = 0;
  879.     while (!done) {
  880.         setVisualPage(vpage);
  881.         ch = getch();
  882.         if (ch == 0) getch();
  883.         switch (ch) {
  884.             case 'u':
  885.                 if (++vpage > maxpage)
  886.                     vpage = 0;
  887.                 break;
  888.             case 'd':
  889.                 if (--vpage < 0)
  890.                     vpage = maxpage;
  891.                 break;
  892.             case 'U':
  893.                 while (!kbhit()) {
  894.                     if (++vpage > maxpage)
  895.                         vpage = 0;
  896.                     setVisualPage(vpage);
  897.                     }
  898.                 getch();
  899.                 break;
  900.             case 'D':
  901.                 while (!kbhit()) {
  902.                     if (--vpage < 0)
  903.                         vpage = maxpage;
  904.                     setVisualPage(vpage);
  905.                     }
  906.                 getch();
  907.                 break;
  908.             case 0xD:
  909.                 done = 1;
  910.                 break;
  911.             case 0x1B:
  912.                 restoreMode();
  913.                 exit(1);
  914.             default:
  915.                 ch -= '1';
  916.                 if (ch >= 0 && ch <= maxpage)
  917.                     vpage = ch;
  918.                 break;
  919.             }
  920.         }
  921.     setActivePage(0);
  922. }
  923.  
  924. void scrollTest(void)
  925. /****************************************************************************
  926. *
  927. * Function:        scrollTest
  928. *
  929. * Description:    Checks the CRT display start routines to scroll the display
  930. *                page up and then back down again.
  931. *
  932. ****************************************************************************/
  933. {
  934.     int        i,max;
  935.  
  936.     if (extendedflipping) {
  937.         if (maxcolor == 15)
  938.             max = (memory*256L) / bytesperline - maxy;
  939.         else
  940.             max = (memory*1024L) / bytesperline - maxy;
  941.         if (max > maxy) max = maxy+1;
  942.         if (max < 0)    return;
  943.  
  944.         setDisplayStart(0,0);
  945.         for (i = 0; i < max; i++) {            /* Scroll the display up    */
  946.             setDisplayStart(0,i);
  947.             if (checkEscape())
  948.                 return;
  949.             }
  950.         if (checkEscape())
  951.             return;
  952.         for (i--; i >= 0; i--) {             /* Scroll the display down  */
  953.             setDisplayStart(0,i);
  954.             if (checkEscape())
  955.                 return;
  956.             }
  957.         }
  958. }
  959.  
  960. void virtualTest(void)
  961. /****************************************************************************
  962. *
  963. * Function:        virtualTest
  964. *
  965. * Description:    Checks the CRT logical scanline length routines, setting
  966. *                up a virtual display buffer and scrolling around within
  967. *                this buffer.
  968. *
  969. ****************************************************************************/
  970. {
  971.     int        i,x,y,scrollx,scrolly,oldmaxx,oldmaxy,max;
  972.     char    buf[80];
  973.  
  974.     if (extendedflipping) {
  975.         /* Find the largest value that we can set the virtual buffer width
  976.          * to that the VBE supports
  977.          */
  978.  
  979.         switch (maxcolor) {
  980.             case 0xF:        max = (memory*2048L) / (maxy+1);    break;
  981.             case 0xFF:        max = (memory*1024L) / (maxy+1);    break;
  982.             case 0x7FFF:
  983.             case 0xFFFF:    max = (memory*512L) / (maxy+1);        break;
  984.             case 0xFFFFFF:    max = (memory*341L) / (maxy+1);        break;
  985.             }
  986.         oldmaxx = maxx;
  987.         oldmaxy = maxy;
  988.         for (i = max; i > oldmaxx+1; i--) {
  989.             setScanlineLength(i,&bytesperline,&maxx,&maxy);
  990.             if (maxx > oldmaxx+1 && maxx < max)
  991.                 break;                /* Large value has been set            */
  992.             }
  993.  
  994.         /* Perform huge horizontal scroll */
  995.  
  996.         setDisplayStart(0,0);
  997.         clearAllPages();
  998.         moire();
  999.         writeText(20,20,"Function 06h - Set/Get Logical Scan Line Length",defcolor);
  1000.         if (maxx == oldmaxx)
  1001.             sprintf(buf,"Virtual buffer could not be resized (still %d x %d pixels)",maxx+1,maxy+1);
  1002.         else
  1003.             sprintf(buf,"Virtual buffer now set to %d x %d pixels",maxx+1,maxy+1);
  1004.         writeText(20,40,buf,defcolor);
  1005.         if (verbose) log("    %s\n", buf);
  1006.         scrollx = maxx-oldmaxx;
  1007.         scrolly = maxy-oldmaxy;
  1008.         for (x = y = 0; x <= scrollx; x++) {
  1009.             setDisplayStart(x,y);
  1010.             if (checkEscape())
  1011.                 return;
  1012.             }
  1013.         for (x = scrollx,y = 0; y <= scrolly; y++) {
  1014.             setDisplayStart(x,y);
  1015.             if (checkEscape())
  1016.                 return;
  1017.             }
  1018.         for (x = scrollx,y = scrolly; x >= 0; x--) {
  1019.             setDisplayStart(x,y);
  1020.             if (checkEscape())
  1021.                 return;
  1022.             }
  1023.         for (x = 0,y = scrolly; y >= 0; y--) {
  1024.             setDisplayStart(x,y);
  1025.             if (checkEscape())
  1026.                 return;
  1027.             }
  1028.         if (maxx == oldmaxx) return;
  1029.  
  1030.         /* Now perform huge vertical scroll */
  1031.  
  1032.         delay(750);
  1033.         setScanlineLength(oldmaxx,&bytesperline,&maxx,&maxy);
  1034.         clearAllPages();
  1035.         moire();
  1036.         writeText(20,20,"Function 06h - Set/Get Logical Scan Line Length",defcolor);
  1037.         sprintf(buf,"Virtual buffer now set to %d x %d pixels",maxx+1,maxy+1);
  1038.         writeText(20,40,buf,defcolor);
  1039.         if (verbose) log("    %s\n",buf);
  1040.         scrolly = maxy-oldmaxy;
  1041.         for (y = 0; y <= scrolly; y++) {
  1042.             setDisplayStart(0,y);
  1043.             if (checkEscape())
  1044.                 return;
  1045.             }
  1046.         for (y = scrolly; y >= 0; y--) {
  1047.             setDisplayStart(0,y);
  1048.             if (checkEscape())
  1049.                 return;
  1050.             }
  1051.         }
  1052. }
  1053.  
  1054. void wideDACTest(void)
  1055. /****************************************************************************
  1056. *
  1057. * Function:        wideDACTest
  1058. *
  1059. * Description:  Displays a set of color values using the wide DAC support
  1060. *                if available.
  1061. *
  1062. ****************************************************************************/
  1063. {
  1064.     int        i,bits,x,y;
  1065.     palette    pal[256];
  1066.     palette    oldpal[256];
  1067.     regs    r;
  1068.  
  1069.     getPalette(0, 256, oldpal);
  1070.  
  1071.     /* Set the DAC into the 8 bit mode if possible */
  1072.  
  1073.     r.ax = 0x4F08;         /* Set DAC service                      */
  1074.     r.bx = 0x0800;         /* BH := 8, BL := 0 (set DAC width)     */
  1075.     if (!callVBE(&r))
  1076.         bits = 6;
  1077.     else bits = r.bx >> 8;
  1078.     if (bits != 6 && bits != 8)
  1079.         fail("Function 08h subfunction 0h returned incorrect value (bh = %d)\n", bits);
  1080.  
  1081.     r.ax = 0x4F08;
  1082.     r.bx = 0x0001;         /* Get DAC width (should now be 8)      */
  1083.     if (!callVBE(&r))
  1084.         fail("Function 08h subfunction 01h failed.\n");
  1085.     if ((r.bx >> 8) != bits)
  1086.         fail("Functions 08h subfunction 01h returned incorrect value (%d instead of %d)\n", r.bx >> 8, bits);
  1087.  
  1088.     memset(pal,0,256*3);
  1089.     for (i = 0; i < 256; i += 4) {
  1090.         pal[64 + (i >> 2)].red = i;
  1091.         pal[128 + (i >> 2)].green = i;
  1092.         pal[192 + (i >> 2)].blue = i;
  1093.         }
  1094.  
  1095.     pal[defcolor].red = 255;
  1096.     pal[defcolor].green = 255;
  1097.     pal[defcolor].blue = 255;
  1098.     setPalette(0,256,pal);
  1099.  
  1100.     clear(0);
  1101.     line(0,0,maxx,0,defcolor);
  1102.     line(0,0,0,maxy,defcolor);
  1103.     line(maxx,0,maxx,maxy,defcolor);
  1104.     line(0,maxy,maxx,maxy,defcolor);
  1105.  
  1106.     x = y = 20;
  1107.     writeText(x,y,"Function 08h - Set/Get DAC width",defcolor);
  1108.     y += 32;
  1109.     if (bits == 8) {
  1110.         if (verbose) log("    8 bit wide DAC supported\n");
  1111.         writeText(x,y,"You should see a smooth transition of colors",defcolor);
  1112.         y += 16;
  1113.         writeText(x,y,"If the colors are broken into 4 lots, the wide DAC is not working",defcolor);
  1114.         y += 32;
  1115.  
  1116.         for (i = 0; i < 192; i++) {
  1117.             line(x+i, y,    x+i, y+32,  64+i/3);
  1118.             line(x+i, y+32, x+i, y+64,  128+i/3);
  1119.             line(x+i, y+64, x+i, y+96,  192+i/3);
  1120.             }
  1121.         }
  1122.     else {
  1123.         writeText(x,y,"BIOS does not support 8 bit wide DAC.",defcolor);
  1124.         if (verbose) log("    8 bit wide DAC NOT supported\n");
  1125.         }
  1126.  
  1127.     delay(750);
  1128.  
  1129.     if (!set6BitPalette())
  1130.         fail("Could not return to 6 bit DAC mode.\n");
  1131.     setPalette(0, 256, oldpal);
  1132. }
  1133.  
  1134. void checkGraphicsFunctions(void)
  1135. /****************************************************************************
  1136. *
  1137. * Function:        checkGraphicsFunctions
  1138. *
  1139. * Description:    Intialises all of the available video modes, and performs
  1140. *                testing on all the modes. We call upon the SuperVGA
  1141. *                test kit to perform the graphics output for us for each
  1142. *                video mode.
  1143. *
  1144. ****************************************************************************/
  1145. {
  1146.     ModeInfoBlock    modeInfo;
  1147.     regs            r;
  1148.     short            *modes;
  1149.  
  1150.     initSuperVGA(true);
  1151.  
  1152.     for (modes = modelist; *modes != -1; modes++) {
  1153.         r.es = SEG(&modeInfo);
  1154.         r.di = OFF(&modeInfo);
  1155.         r.ax = 0x4F01;
  1156.         r.cx = *modes;
  1157.         if (bits >= 0x100 && *modes != bits)
  1158.             continue;
  1159.         if (callVBE(&r)) {
  1160.             if ((modeInfo.ModeAttributes & 0x1) == 0)
  1161.                 continue;
  1162.             if (modeInfo.MemoryModel < 3)
  1163.                 continue;
  1164.             if (bits != 0 && bits < 0x100 && modeInfo.BitsPerPixel != bits)
  1165.                 continue;
  1166.             startModeCheck(*modes);
  1167.             setSuperVGAMode(*modes);
  1168.             checkEscape();
  1169.             if (doPageTest)
  1170.                 pageTest(*modes);
  1171.             else {
  1172.                 moire();
  1173.                 dumpModeInfo(*modes,true);
  1174.                 scrollTest();
  1175.                 checkEscape();
  1176.                 delay(750);
  1177.                 }
  1178.             if (maxcolor == 255)
  1179.                 wideDACTest();
  1180.             checkEscape();
  1181.             if (!doPageTest)
  1182.                 virtualTest();
  1183.             delay(750);
  1184.             restoreMode();
  1185.             endModeCheck();
  1186.             }
  1187.         checkEscape();
  1188.         }
  1189. }
  1190.  
  1191. void banner(void)
  1192. {
  1193.     out("VBETest - VESA VBE stress test program (Version %s)\n", version);
  1194.     out("          Copyright (C) 1994 SciTech Software\n\n");
  1195. }
  1196.  
  1197. void help(void)
  1198. {
  1199.     banner();
  1200.     printf("Usage: vbetest [-vph] [-b<bits>] [-m<mode>]\n\n");
  1201.     printf("By specifying the number of 'bits' to test, you can restrict VBETest to\n");
  1202.     printf("run the time consuming graphical test only for the modes with the specified\n");
  1203.     printf("number of bits per pixel. Likewise you can specify a single 'mode' (in hex).\n\n");
  1204.     printf("For example:\n");
  1205.     printf("    vbetest -b8   - Test all 8 bits per pixel (256 color) video modes\n");
  1206.     printf("    vbetest -m101 - Test only mode 101h (640x480x256)\n\n");
  1207.     printf("Options are:\n");
  1208.     printf("    -v    - Dump verbose debugging information to the VBETEST.LOG file\n");
  1209.     printf("    -p    - Interactive CRTC paging (otherwise uses CRTC scrolling)\n");
  1210.     printf("    -b<x> - Only test modes with 'x' bits per pixel\n");
  1211.     printf("    -m<x> - Only test mode with internal mode number 'x'\n");
  1212.     printf("    -h    - Display this help information\n");
  1213.     exit(1);
  1214. }
  1215.  
  1216. void main(int argc, char *argv[])
  1217. {
  1218.     int            option;
  1219.     char        *argument;
  1220.  
  1221.     if (queryCpu() < 4) {
  1222.         printf("This program contains '386 specific instructions, and will not work on\n");
  1223.         printf("this machine - sorry\n");
  1224.         }
  1225.  
  1226.     do {
  1227.         option = getopt(argc,argv,"vVpPhHb:B:m:M:",&argument);
  1228.         if (isascii(option))
  1229.             option = tolower(option);
  1230.         switch(option) {
  1231.             case 'v':
  1232.                 verbose = true;
  1233.                 break;
  1234.             case 'p':
  1235.                 doPageTest = true;
  1236.                 break;
  1237.             case 'b':
  1238.                 bits = atoi(argument);
  1239.                 break;
  1240.             case 'm':
  1241.                 sscanf(argument, "%x", &bits);
  1242.                 break;
  1243.             case 'h':
  1244.             case PARAMETER:
  1245.             case INVALID:
  1246.                 help();
  1247.             }
  1248.         } while (option != ALLDONE);
  1249.  
  1250.     if ((logfile = fopen("vbetest.log","wt")) == NULL) {
  1251.         out("Unable to open log file!!\n");
  1252.         exit(1);
  1253.         }
  1254.  
  1255.     banner();
  1256.     printf("This program will test every function in the VESA VBE interface specifications\n");
  1257.     printf("for correct conformance. If any errors are encountered, they will be logged to\n");
  1258.     printf("the file 'vbetest.log' in the current directory.\n\n");
  1259.     printf("Hit any key to start, or ESC anytime to cancel.\n");
  1260.  
  1261.     if (getch() == 0x1B)
  1262.         exit(1);
  1263.  
  1264.     checkFunction00h();
  1265.     checkFunction01h();
  1266.     checkFunction02h();
  1267.     checkFunction04h();
  1268.     checkFunction05h();
  1269.  
  1270.     checkGraphicsFunctions();
  1271.  
  1272.     log("\n");
  1273.     if (failed)
  1274.         out("Video BIOS failed conformance test. Check log report for details.\n");
  1275.     else if (!extendedflipping) {
  1276.         out("Video BIOS passed most tests, but does not implement extended CRT\n");
  1277.         out("addressing, used by some newer programs (like Microsoft Flight\n");
  1278.         out("simulator\n");
  1279.         }
  1280.     else
  1281.         out("Congratulations! Video BIOS passed all conformance tests.\n");
  1282. }
  1283.